package com.xoms.front.util.pay.ali;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradeCancelModel;
import com.alipay.api.domain.AlipayTradePayModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradePayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.xoms.front.constants.StringConstants;

public class AliPayManager {

	private static final String SUCCESS = "success";
	private static final String FAIL = "failure";

	// 实例化客户端
	private static AlipayClient alipayClient;

	private static AliPayManager instance;

	private AliPayManager() {
		// 初始化
		alipayClient = new DefaultAlipayClient(StringConstants.getInstance().ALIPAY_GATE_WAY,
				StringConstants.getInstance().ALIPAY_APP_ID, StringConstants.getInstance().ALIPAY_APP_PRIVATE_KEY,
				"json", StringConstants.getInstance().ALIPAY_CHARSET, StringConstants.getInstance().ALIPAY_PUBLIC_KEY,
				StringConstants.getInstance().ALIPAY_SIGN_TYPE);
	}

	public static AliPayManager getInstance() {
		synchronized (AliPayManager.class) {
			if (instance == null) {
				instance = new AliPayManager();
			}
			return instance;
		}
	}

	/**
	 * 扫码支付
	 * 
	 * @param outTradeNo
	 *            商户订单号，需要保证不重复
	 * @param subject
	 *            订单标题
	 * @param storeId
	 *            商户门店编号
	 * @param totalAmount
	 *            订单金额 元
	 * @param notifyUrl
	 *            支付回调地址
	 * @return
	 */
	public AlipayTradePrecreateResponse scanQrcode2Store(String outTradeNo, String subject, String storeId,
			double totalAmount, String notifyUrl) {
		AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();// 创建API对应的request类
		// SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
		AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
		model.setOutTradeNo(outTradeNo);
		model.setSubject(subject);
		model.setStoreId(storeId);
		model.setTimeoutExpress("90m"); // 交易超时时间
		model.setTotalAmount(String.valueOf(totalAmount));
		request.setBizModel(model);
		request.setNotifyUrl(notifyUrl);
		// 通过alipayClient调用API，获得对应的response类
		AlipayTradePrecreateResponse response = null;
		try {
			response = alipayClient.execute(request);
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		// 根据response中的结果继续业务逻辑处理
		return response;
	}

	/**
	 * 当面付
	 * 
	 * @param outTradeNo
	 *            商户订单号，需要保证不重复
	 * @param authCode
	 *            用户付款码，25~30开头的长度为16~24位的数字，实际字符串长度以开发者获取的付款码长度为准
	 * @param subject
	 *            订单标题
	 * @param storeId
	 *            商户门店编号
	 * @param totalAmount
	 *            订单金额 元
	 * @return
	 */
	public AlipayTradePayResponse scanAuthCode2Store(String outTradeNo, String authCode, String subject, String storeId,
			double totalAmount) {
		AlipayTradePayRequest request = new AlipayTradePayRequest(); // 创建API对应的request类
		// SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
		AlipayTradePayModel model = new AlipayTradePayModel();
		model.setOutTradeNo(outTradeNo);
		model.setScene("bar_code"); // 条码支付固定传入bar_code
		model.setAuthCode(authCode);
		model.setSubject(subject);
		model.setStoreId(storeId);
		model.setTimeoutExpress("2m"); // 交易超时时间
		model.setTotalAmount(String.valueOf(totalAmount));
		request.setBizModel(model);
		// 通过alipayClient调用API，获得对应的response类
		AlipayTradePayResponse response = null;
		try {
			response = alipayClient.execute(request);
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		// 根据response中的结果继续业务逻辑处理
		return response;
	}

	/**
	 * 交易查询接口alipay.trade.query
	 * 
	 * @param outTradeNo
	 *            支付时传入的商户订单号，与trade_no必填一个
	 * @param tradeNo
	 *            支付时返回的支付宝交易号，与out_trade_no必填一个
	 * @return
	 */
	public AlipayTradeQueryResponse tradeQuery(String orderNo, String tradeNo) {
		AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();// 创建API对应的request类
		// 设置业务参数
		AlipayTradeQueryModel model = new AlipayTradeQueryModel();
		if (orderNo != null && orderNo != "") {
			model.setOutTradeNo(orderNo);
		} else {
			model.setTradeNo(tradeNo);
		}
		request.setBizModel(model);
		AlipayTradeQueryResponse response = null;
		try {
			// 通过alipayClient调用API，获得对应的response类
			response = alipayClient.execute(request);
			System.out.print(response.getBody());
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		return response;
		// 根据response中的结果继续业务逻辑处理
	}

	/**
	 * 交易撤销接口alipay.trade.cancel
	 * 
	 * @param outTradeNo
	 *            支付时传入的商户订单号，与trade_no必填一个
	 * @param tradeNo
	 *            支付时返回的支付宝交易号，与out_trade_no必填一个
	 * @return
	 */
	public AlipayTradeCancelResponse tradeCancel(String outTradeNo, String tradeNo) {
		AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();// 创建API对应的request类
		// 设置业务参数
		AlipayTradeCancelModel model = new AlipayTradeCancelModel();
		model.setOutTradeNo(outTradeNo);
		model.setTradeNo(tradeNo);
		request.setBizModel(model);
		AlipayTradeCancelResponse response = null;
		try {
			// 通过alipayClient调用API，获得对应的response类
			response = alipayClient.execute(request);
			System.out.print(response.getBody());
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		return response;
		// 根据response中的结果继续业务逻辑处理
	}

	/**
	 * 返回app端支付，签名后的订单信息
	 * 
	 * @param body
	 *            对一笔交易的具体描述信息
	 * @param subject
	 *            商品的标题/交易标题/订单标题/订单关键字等
	 * @param outTradeNo
	 *            商户网站唯一订单号
	 * @param totalAmount
	 *            订单总金额，单位为分
	 * @param notifyUrl
	 *            商户外网可以访问的异步地址,异步通知商户服务器
	 * @return
	 */
	public String getAppPay(String body, String subject, String outTradeNo, int totalAmount, String notifyUrl) {
		// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
		AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
		// SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
		AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
		model.setBody(body);
		model.setSubject(subject);
		model.setOutTradeNo(outTradeNo);
		model.setTimeoutExpress("30m");
		model.setTotalAmount(String.valueOf(totalAmount / 100.0));
		model.setProductCode("QUICK_MSECURITY_PAY");
		request.setBizModel(model);
		request.setNotifyUrl(notifyUrl);
		try {
			// 这里和普通的接口调用不同，使用的是sdkExecute
			AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
			System.out.println(response.getBody());// 就是orderString 可以直接给客户端请求，无需再做处理。
			return response.getBody();
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}

		return null;
	}

	public String getAppId() {
		return StringConstants.getInstance().ALIPAY_APP_ID;
	}

	public String getAccount() {
		return StringConstants.getInstance().ALIPAY_ACCOUNT;
	}

	public static String getAlipayPublicKey() {
		return StringConstants.getInstance().ALIPAY_PUBLIC_KEY;
	}

	public static String getSigntype() {
		return StringConstants.getInstance().ALIPAY_SIGN_TYPE;
	}

	public static String getCharset() {
		return StringConstants.getInstance().ALIPAY_CHARSET;
	}

	// 处理成功
	public String getPayResponseSucess() {
		return SUCCESS;
	}

	// 处理失败，支付宝服务器起回不断重发通知
	public String getPayResponseFail() {
		return FAIL;
	}

}
